package meta

import (
	"github.com/micro-plat/hydra"
	"github.com/micro-plat/lib4go/errs"
	"github.com/micro-plat/lib4go/types"
)

// AddMetaTable 添加元表
func AddMetaTable(tenantID int, tableTitle, tableName, description string, columns []interface{}) (types.IXMap, error) {
	db, err := hydra.C.DB().GetRegularDB().Begin()
	if err != nil {
		return nil, err
	}

	exists, err := metaTableExists(db, tenantID, tableName)
	if err != nil {
		return nil, err
	}
	if exists {
		return nil, errs.NewErrorf(10001, "表(%s)已存在", tableName)
	}

	params := map[string]interface{}{
		"tenant_id":   tenantID,
		"title":       tableTitle,
		"name":        tableName,
		"description": description,
	}

	tableID, eff, err := db.Executes(sqlInsertMetaTable, params)
	if err != nil || eff == 0 {
		db.Rollback()
		return nil, errs.GetDBError(eff, err)
	}

	// 字段数据保存到元数据表
	columnNames := make(map[string]bool, len(columns))
	for _, icolumn := range columns {
		column := types.NewXMap()
		column.MergeMap(icolumn.(map[string]interface{}))
		columnTitle := column.GetString("title")
		columnName := column.GetString("name")
		columnType := column.GetString("type")
		source := column.GetString("source")
		method := column.GetString("method")
		param := column.GetString("param")
		isNullable := column.GetBool("is_nullable")
		isPrefab := column.GetBool("is_prefab")
		isDictLabel := column.GetBool("is_dict_label")
		isLikeQuery := column.GetBool("is_like_query")
		description := column.GetString("title")

		// 判断字段名称是否重复
		if _, ok := columnNames[columnName]; ok {
			db.Rollback()
			return nil, errs.NewErrorf(10001, "字段(%s)名称重复", columnName)
		}
		columnNames[columnName] = true

		// 添加字段数据到元数据表
		_, err = addMetaColumnByDB(db, tenantID, tableID, columnTitle, columnName, columnType, isNullable, isDictLabel, isLikeQuery, source, method, param, isPrefab, description)
		if err != nil {
			db.Rollback()
			return nil, err
		}
	}
	// 获取数据表信息
	table, err := getMetaTableByID(db, tenantID, tableID)
	if err != nil {
		db.Rollback()
		return nil, err
	}

	// 应用数据表
	err = apply(db, table)
	if err != nil {
		db.Rollback()
		return nil, err
	}
	db.Commit()
	return table, nil
}

func GetMetaTables(tenantID int, name string, tableId ...int64) (types.XMaps, error) {
	db := hydra.C.DB().GetRegularDB()
	params := map[string]interface{}{
		"tenant_id": tenantID,
		"table_id":  types.GetInt64ByIndex(tableId, 0),
		"name":      name,
	}
	if types.GetInt64ByIndex(tableId, 0) == 0 {
		delete(params, "table_id")
	}

	rows, err := db.Query(sqlGetTablesAndColumns, params)
	if err != nil {
		return nil, err
	}
	result := colums2TableColumns(rows)
	return result, nil

}

// UpdateMetaTable 更新元表描述
func UpdateMetaTable(tenantID int, tableID int64, title, description string) (types.IXMap, error) {
	db, err := hydra.C.DB().GetRegularDB().Begin()
	if err != nil {
		return nil, err
	}
	params := map[string]interface{}{
		"table_id":    tableID,
		"tenant_id":   tenantID,
		"title":       title,
		"description": description,
	}
	eff, err := db.Execute(sqlUpdateMetaTable, params)
	if err != nil || eff == 0 {
		db.Rollback()
		return nil, errs.GetDBError(eff, err)
	}

	metaTable, err := getMetaTableByID(db, tenantID, tableID)
	if err != nil {
		db.Rollback()
		return nil, err
	}

	// 应用数据表
	err = apply(db, metaTable)
	if err != nil {
		db.Rollback()
		return nil, err
	}

	db.Commit()
	return metaTable, err
}

// DeleteMetaTable 删除元表
func DeleteMetaTable(tableID, tenantID int) error {
	params := map[string]interface{}{
		"table_id":  tableID,
		"tenant_id": tenantID,
	}
	db := hydra.C.DB().GetRegularDB()
	_, err := db.Execute(sqlDeleteMetaTable, params)
	return err
}
